home *** CD-ROM | disk | FTP | other *** search
- #include <stdio.h>
- #include <std.h>
- #include <sys/types.h>
- #include <dos.h>
- #include <pc.h>
- #include <go32.h>
- #include <dpmi.h>
- #define far
- #include "ed.h"
- #include "unassmbl.h"
- #include "serial.h"
- #include "syms.h"
-
- #define MaxPort 4
-
- static int UartBase[MaxPort] = { 0x3F8, 0x2F8, 0x3E8, 0x2E8 };
- static int IntNums [MaxPort] = { 0x0C, 0x0B, 0x0C, 0x0B };
- static int I8259Levels[MaxPort] = {4, 3, 4, 3};
- static int ComInstalled = 0;
-
- static unsigned int UartData; /*Data register*/
- static unsigned int UartIer ; /*Interrupt enable register*/
- static unsigned int UartIir ; /*Interrupt identification register*/
- static unsigned int UartLcr ; /*Line control register*/
- static unsigned int UartMcr ; /*Modem control register*/
- static unsigned int UartLsr ; /*Line status register*/
- static unsigned int UartMsr ; /*Modem status register*/
- static unsigned int UartSpr ; /*Scratch pad register */
-
- static unsigned char OldIer, OldMcr;
- static unsigned int OldI8259Mask;
-
- static _go32_dpmi_seginfo rm_old_irq;
- static _go32_dpmi_registers rm_regs;
- static _go32_dpmi_seginfo rm_si;
- static _go32_dpmi_seginfo pm_old_irq;
- static _go32_dpmi_seginfo pm_si;
-
- static _go32_dpmi_seginfo rm_old_irq_1c;
- static _go32_dpmi_registers rm_regs_1c;
- static _go32_dpmi_seginfo rm_si_1c;
-
- static unsigned int I8259Bit;
- static unsigned int IntNum;
-
- typedef char *comnames;
- static comnames DOSDEV[5] = { "CON", "COM1", "COM2", "COM3", "COM4" };
-
- volatile unsigned long eip, ebp, esp, eflag;
-
- #define RxQueueSize 4096
- #define TxQueueSize 4096
- static char RxQueue[RxQueueSize];
- static char TxQueue[TxQueueSize];
- static unsigned int RxIn, RxOut, TxIn, TxOut; /*Index of next character*/
- static unsigned int RxChars, TxChars; /*Number of chars in queue*/
- static int curr_port = 0;
- static int int_1c_counts = 0;
- static word32 caller_address = 0;
- static word32 caller_value = 0;
- extern int is_in_running_mode;
-
- /* ---------------------------------------------------------------------- */
- static char *stack;
- static word32 my_esp, my_ebp, my_ss, old_esp, old_ebp, old_ss;
- static switch_stack = 0;
- /* ---------------------------------------------------------------------- */
- static void
- refresh_uart (void)
- { /* outportb (UartIer, 0); */
- asm ("xor %al, %al \n\
- mov _UartIer, %dx \n\
- out %al, %dx");
- /* outportb (0x21, OldI8259Mask | I8259Bit); */
- asm ("mov $0x21, %dx \n\
- mov _OldI8259Mask, %al \n\
- or _I8259Bit, %al \n\
- out %al, %dx");
- /* outportb (UartLcr, 3); */
- asm ("mov $0x03, %al \n\
- mov _UartLcr, %dx \n\
- out %al, %dx");
- /* outportb (UartMcr, 0x0a | (OldMcr & 1)); */
- asm ("mov _UartMcr, %dx \n\
- mov _OldMcr, %al \n\
- and $0x01, %al \n\
- or $0x0a, %al \n\
- out %al, %dx");
- /* outportb (UartIer, inportb (UartIer) | 1);*/
- asm ("mov _UartIer, %dx \n\
- in %dx, %al \n\
- or $0x01, %al \n\
- out %al, %dx");
- /*outportb (0x21, inportb (0x21) & ~I8259Bit);*/
- asm ("mov $0x21, %dx \n\
- mov _I8259Bit, %cl \n\
- not %cl \n\
- in %dx, %al \n\
- and %cl, %al \n\
- out %al, %dx");
- TxChars = 0;
- TxIn = 0;
- TxOut = 0;
- }
- /* ---------------------------------------------------------------------- */
- static void
- rm_isr_1c (void)
- { if (is_in_running_mode)
- { if (++int_1c_counts >= 18)
- { refresh_uart ();
- int_1c_counts = 0;
- }
- }
- }
- /* ---------------------------------------------------------------------- */
- static int ch, Iir, ctrl_c_hit;
- /* ---------------------------------------------------------------------- */
- static void
- ComInterruptDriver (void)
- {
- asm("cli");
- /* if (switch_stack)
- asm("movl %esp, %eax \n\
- movl %eax, _old_esp \n\
- movl %ebp, %eax \n\
- movl %eax, _old_ebp \n\
- movw %ss, %ax \n\
- movw %ax, _old_ss \n\
- movl _my_esp, %eax \n\
- movl %eax, %esp \n\
- movl _my_ebp, %eax \n\
- movl %eax, %ebp \n\
- movw _my_ss, %ax \n\
- movw %ax, %ss \n\
- "); */
- Iir = inportb (UartIir);
- while (!(Iir % 2))
- {
- ch = 0;
- switch (Iir >> 1)
- {
- case 2:
- ch = inportb (UartData); /* realmode: cannot get accurate eip. */
- if (ch == 3)
- ctrl_c_hit = 1;
- if (RxChars < RxQueueSize)
- {
- RxQueue [RxIn] = ch;
- RxIn++;
- if (RxIn >= RxQueueSize)
- RxIn = 0;
- RxChars++;
- }
- break;
- case 1:
- if (TxChars <= 0)
- outportb (UartIer, inportb (UartIer) & ~2);
- else if ((inportb (UartLsr) >> 5) %2)
- {
- outportb (UartData, TxQueue [TxOut]);
- TxOut++;
- if (TxOut >= TxQueueSize)
- TxOut = 0;
- TxChars--;
- }
- break;
- case 0:
- (void) inportb (UartMsr);
- break;
- case 3:
- ch = inportb (UartLsr);
- break;
- }
- Iir = inportb (UartIir);
- }
- outportb (0x20, 0x20);
- /* if (switch_stack)
- asm("movl %esp, %eax \n\
- movl %eax, _my_esp \n\
- movl %ebp, %eax \n\
- movl %eax, _my_ebp \n\
- movl _old_esp, %eax \n\
- movl %eax, %esp \n\
- movl _old_ebp, %eax \n\
- movl %eax, %ebp \n\
- movw _old_ss, %ax \n\
- movw %ax, %ss \n\
- leave \n\
- ret \n\
- "); */
- }
- /* ---------------------------------------------------------------------- */
- static void
- pmComInterruptDriver (_go32_dpmi_registers r)
- {
- asm("cli \n\
- push %eax \n\
- push %ebx \n\
- push %ecx \n\
- push %edx \n\
- push %esi \n\
- push %edi \n\
- ");
- asm("push %ds \n\
- movw $0x107, %ax \n\
- movw %ax, %ds \n\
- ");
- /* if (switch_stack)
- asm("movl %esp, %eax \n\
- movl %eax, _old_esp \n\
- movl %ebp, %eax \n\
- movl %eax, _old_ebp \n\
- movw %ss, %ax \n\
- movw %ax, _old_ss \n\
- movl _my_esp, %eax \n\
- movl %eax, %esp \n\
- movl _my_ebp, %eax \n\
- movl %eax, %ebp \n\
- movw _my_ss, %ax \n\
- movw %ax, %ss \n\
- "); */
-
- Iir = inportb (UartIir);
-
- while (!(Iir % 2))
- {
- switch (Iir >> 1)
- {
- case 2:
- ch = inportb (UartData);
- if (ch == 3)
- ctrl_c_hit = 1;
- if (RxChars < RxQueueSize)
- {
- RxQueue [RxIn] = ch;
- RxIn++;
- if (RxIn >= RxQueueSize)
- RxIn = 0;
- RxChars++;
- }
- break;
- case 1:
- if (TxChars <= 0)
- outportb (UartIer, inportb (UartIer) & ~2);
- else if ((inportb (UartLsr) >> 5) %2)
- {
- outportb (UartData, TxQueue [TxOut]);
- TxOut++;
- if (TxOut >= TxQueueSize)
- TxOut = 0;
- TxChars--;
- }
- break;
- case 0:
- (void) inportb (UartMsr);
- break;
- case 3:
- ch = inportb (UartLsr);
- break;
- }
- Iir = inportb (UartIir);
- }
- if (ctrl_c_hit)
- { ctrl_c_hit = 0;
- if (is_in_running_mode && !switch_stack)
- { asm("movl %ebp,%eax");
- asm("add $0x0c,%eax");
- asm("movl (%eax),%edx");
- asm("movl %edx,_eflag");
- eflag |= 0x0100;
- asm("movl %ebp,%eax");
- asm("add $0x0c,%eax");
- asm("movl _eflag,%edx");
- asm("movl %edx,(%eax)");
- }
- }
- asm("mov $0x20,%al");
- asm("out %al,$0x20");
-
- /* if (switch_stack)
- asm("movl %esp, %eax \n\
- movl %eax, _my_esp \n\
- movl %ebp, %eax \n\
- movl %eax, _my_ebp \n\
- movl _old_esp, %eax \n\
- movl %eax, %esp \n\
- movl _old_ebp, %eax \n\
- movl %eax, %ebp \n\
- movw _old_ss, %ax \n\
- movw %ax, %ss \n\
- "); */
- asm("pop %ds");
- asm("pop %edi \n\
- pop %esi \n\
- pop %edx \n\
- pop %ecx \n\
- pop %ebx \n\
- pop %eax \n\
- leave \n\
- iret \n\
- ");
- }
- /* ---------------------------------------------------------------------- */
- static void
- com_install_refresh_int (void)
- { int ret;
- word32 value;
-
- value = (word32) refresh_uart;
- caller_address = syms_name2val ("Dosx_call_debugger_every_sec");
- if (undefined_symbol)
- { undefined_symbol = 0;
- caller_address = 0;
- }
- if (caller_address)
- { read_child (caller_address, &caller_value, sizeof (word32));
- write_child (caller_address, &value, sizeof (word32));
- } else
- { rm_si_1c.pm_offset = (int) rm_isr_1c;
- ret = _go32_dpmi_allocate_real_mode_callback_iret(&rm_si_1c, &rm_regs_1c);
- disable();
- _go32_dpmi_get_real_mode_interrupt_vector(0x1c, &rm_old_irq_1c);
- _go32_dpmi_set_real_mode_interrupt_vector(0x1c, &rm_si_1c);
- enable();
- }
- }
- /* ---------------------------------------------------------------------- */
- static void
- com_remove_refresh_int (void)
- { if (caller_address)
- { write_child (caller_address, &caller_value, sizeof (word32));
- } else
- { disable ();
- _go32_dpmi_set_real_mode_interrupt_vector(0x1c, &rm_old_irq_1c);
- _go32_dpmi_free_real_mode_callback(&rm_si_1c);
- enable ();
- }
- }
- /* ---------------------------------------------------------------------- */
- static int
- com_install_rm_irq (int vect_num)
- { int ret;
-
- rm_si.pm_offset = (int) ComInterruptDriver;
- ret = _go32_dpmi_allocate_real_mode_callback_iret(&rm_si, &rm_regs);
- if (ret)
- return 0;
-
- disable();
- _go32_dpmi_get_real_mode_interrupt_vector(vect_num, &rm_old_irq);
- _go32_dpmi_set_real_mode_interrupt_vector(vect_num, &rm_si);
- enable();
-
- com_install_refresh_int ();
-
- return 1;
- }
- /* ---------------------------------------------------------------------- */
- static void
- com_remove_rm_irq (int vect_num)
- { com_remove_refresh_int ();
- disable();
- _go32_dpmi_set_real_mode_interrupt_vector(vect_num, &rm_old_irq);
- _go32_dpmi_free_real_mode_callback(&rm_si);
- enable();
- }
- /* ---------------------------------------------------------------------- */
- static void
- com_install_pm_irq (int vect_num)
- { disable();
- _go32_dpmi_get_protected_mode_interrupt_vector(vect_num, &pm_old_irq);
- pm_si.pm_offset = (int) pmComInterruptDriver;
- pm_si.pm_selector = _go32_my_cs();
- _go32_dpmi_set_protected_mode_interrupt_vector(vect_num, &pm_si);
- enable();
- }
- /* ---------------------------------------------------------------------- */
- static void
- com_remove_pm_irq (int vect_num)
- { disable();
- _go32_dpmi_set_protected_mode_interrupt_vector(vect_num, &pm_old_irq);
- enable();
- }
- /* ---------------------------------------------------------------------- */
- static int
- install_irq (int vect_num)
- { if (_go32_info_block.run_mode == _GO32_RUN_MODE_DPMI)
- { switch_stack = 1;
- stack = (char *)1; /* malloc (0x4000); */
- if (!stack)
- return (0);
- my_esp = (word32)stack + 0x4000 - 8;
- my_ebp = my_esp;
- old_esp = 0;
- old_ebp = 0;
- old_ss = 0;
- }
- my_ss = _go32_my_ds ();
- write_child ((word32)pmComInterruptDriver + 0x0d, &my_ss, 2);
-
- if (!com_install_rm_irq(vect_num))
- return 0;
- com_install_pm_irq(vect_num);
- return 1;
- }
- /* ---------------------------------------------------------------------- */
- static void
- remove_irq (int vect_num)
- { com_remove_rm_irq(vect_num);
- com_remove_pm_irq(vect_num);
- }
- /* ---------------------------------------------------------------------- */
- void
- com_flush_rx (void)
- { disable();
- RxChars = 0;
- RxIn = 0;
- RxOut = 0;
- enable();
- }
- /* ---------------------------------------------------------------------- */
- void
- com_flush_tx (void)
- { disable();
- TxChars = 0;
- TxIn = 0;
- TxOut = 0;
- enable();
- }
- /* ---------------------------------------------------------------------- */
- int
- com_carrier (void)
- { return ComInstalled && ((inportw (UartMsr) >> 7) %2);
- }
- /* ---------------------------------------------------------------------- */
- int
- com_tx_ready (void)
- { return (TxChars < TxQueueSize);
- }
- /* ---------------------------------------------------------------------- */
- int
- com_tx_empty (void)
- { return (TxChars == 0);
- }
- /* ---------------------------------------------------------------------- */
- int
- com_rx_empty (void)
- { return (RxChars == 0);
- }
- /* ---------------------------------------------------------------------- */
- void
- com_lower_dtr (void)
- { if (ComInstalled)
- { disable();
- outportb (UartMcr, inportb (UartMcr) & ~1);
- enable();
- }
- }
- /* ---------------------------------------------------------------------- */
- void
- com_raise_dtr (void)
- { if (ComInstalled)
- { disable();
- outportb (UartMcr, inportb (UartMcr) | 1);
- enable();
- }
- }
- /* ---------------------------------------------------------------------- */
- void
- com_set_speed (unsigned int Speed)
- { int Divisor;
- if (ComInstalled)
- { if (Speed < 2)
- Speed = 2;
- Divisor = 115200L / Speed;
- disable();
- outportb (UartLcr, inportb (UartLcr) | 0x80);
- outportw (UartData, Divisor);
- outportb (UartLcr, inportb (UartLcr) & ~0x80);
- enable();
- }
- }
- /* ---------------------------------------------------------------------- */
- void
- com_set_parity (void)
- { int Lcr;
- Lcr = 0x00 | 0x03;
- disable();
- outportb (UartLcr, (inportb (UartLcr) & 0x40) | Lcr);
- enable();
- }
- /* ---------------------------------------------------------------------- */
- int
- com_install (int PortNum)
- { if (ComInstalled)
- return 3;
- if ((PortNum < 1) || (PortNum > MaxPort))
- return 1;
-
- UartData = UartBase [PortNum - 1];
- UartIer = UartData + 1;
- UartIir = UartData + 2;
- UartLcr = UartData + 3;
- UartMcr = UartData + 4;
- UartLsr = UartData + 5;
- UartMsr = UartData + 6;
- UartSpr = UartData + 7;
- IntNum = IntNums [PortNum - 1];
- I8259Bit = 1 << I8259Levels [PortNum - 1];
-
- OldIer = inportb (UartIer);
- outportb (UartIer, 0);
- if (inportb (UartIer) != 0)
- return 2;
-
- disable();
- OldI8259Mask = inportb (0x21);
- outportb (0x21, OldI8259Mask | I8259Bit);
- enable();
-
- com_flush_tx();
- com_flush_rx();
-
- if (!install_irq (IntNum))
- return 4;
- ComInstalled = 1;
-
- outportb (UartLcr, 3);
-
- disable();
- OldMcr = inportb (UartMcr);
- outportb (UartMcr, 0x0a | (OldMcr & 1));
- enable();
-
- outportb (UartIer, 1);
-
- disable();
- outportb (0x21, inportb (0x21) & ~I8259Bit);
- enable();
-
- curr_port = PortNum;
- return 0;
- }
- /* ---------------------------------------------------------------------- */
- static void
- redirect_init (int dev_num)
- { freopen (DOSDEV[dev_num], "w", stderr);
- freopen (DOSDEV[dev_num], "r", stdin);
- freopen (DOSDEV[dev_num], "w", stdout);
- }
- /* ---------------------------------------------------------------------- */
- static void
- redirect_done (void)
- { redirect_init (0);
- }
- /* ---------------------------------------------------------------------- */
- int
- com_init (int port_num)
- { int i;
-
- i = com_install (port_num);
- if (i)
- return i;
- com_set_speed (9600);
- com_set_parity();
- redirect_init (port_num);
- ComInstalled = 1;
- return 0;
- }
- /* ---------------------------------------------------------------------- */
- void
- com_done (void)
- { if (ComInstalled)
- { ComInstalled = 0;
- outportb (UartMcr, OldMcr);
- outportb (UartIer, OldIer);
- disable();
- outportb (0x21, ((inportb (0x21) & ~I8259Bit) | OldI8259Mask) & I8259Bit);
- enable();
- remove_irq (IntNum);
- redirect_done ();
- }
- }
- /* ---------------------------------------------------------------------- */
- int
- com_rx (void)
- { int temp = 0;
-
- if (!RxChars)
- return 0;
- if (!ComInstalled)
- return 0;
- asm("cli");
- temp = RxQueue[RxOut];
- RxOut++;
- if (RxOut >= RxQueueSize)
- RxOut = 0;
- RxChars--;
- asm("sti");
- return temp;
- }
- /* ---------------------------------------------------------------------- */
- void
- com_tx (int ch)
- { if (ComInstalled)
- { do {
- } while (!com_tx_ready);
- asm("cli");
- TxQueue [TxIn] = ch;
- TxIn++;
- if (TxIn >= TxQueueSize)
- TxIn = 0;
- TxChars++;
- outportb (UartIer, inportb (UartIer) | 2);
- asm("sti");
- }
- }
- /* ---------------------------------------------------------------------- */
- void
- com_txs (char *s)
- { if (ComInstalled)
- { while (*s)
- { do {
- } while (TxChars >= TxQueueSize);
- asm("cli");
- do {
- TxQueue [TxIn] = *s++;
- TxIn++;
- if (TxIn >= TxQueueSize)
- TxIn = 0;
- TxChars++;
- } while ((TxChars < TxQueueSize) && (*s));
- outportb (UartIer, inportb (UartIer) | 2);
- asm("sti");
- }
- }
- }
- /* ---------------------------------------------------------------------- */
-